package com.yang.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.extra.mail.MailUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yang.domain.Captcha;
import com.yang.domain.User;
import com.yang.domain.dto.user.RegisterUser;
import com.yang.domain.dto.user.RemakePasswordUser;
import com.yang.handler.UserThreadLocal;
import com.yang.mapper.CaptchaMapper;
import com.yang.mapper.UserMapper;
import com.yang.service.UserService;
import com.yang.utils.CommonUtils;
import com.yang.utils.JwtUtil;
import com.yang.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

/**
 * @author 93879
 * @description 针对表【user(用户表)】的数据库操作Service实现
 * @createDate 2024-02-16 21:24:31
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {
    @Autowired
    private CaptchaMapper captchaMapper;
    @Override
    public R login(String username, String password) {
        // 判断账号密码是否为空
        if (StrUtil.isEmpty(username) || StrUtil.isEmpty(password)) {
            return R.error("账号或密码为空");
        }
        // 判断该账号是否已经注册
        User selectOne = baseMapper.selectOne(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, username));
        // 账号不存在
        if (ObjUtil.isEmpty(selectOne)) {
            return R.error("账号不存在");
        }
        // 加密后的密码
        String encrypt = DigestUtil.md5Hex(password);
        // 登陆成功
        if (encrypt.equals(selectOne.getPassword()) && 0 == selectOne.getDelFlag()) {
            baseMapper.update(null, new LambdaUpdateWrapper<User>()
                    .set(User::getLastLoginTime, LocalDateTime.now())
                    .eq(User::getUsername, username));
            // 返回token
            String token = JwtUtil.createJWT(selectOne.getId().toString());
            selectOne.setToken(token);
            return R.ok("登陆成功").setData(selectOne);
        }
        // 密码错误
        return R.error("密码错误");
    }

    @Override
    public R register(RegisterUser registerUser) {
        // 校验验证码
        String uuid = registerUser.getCaptcha().getUuid();
        // 查找验证码
        Captcha captcha = captchaMapper.selectById(uuid);
        if(StrUtil.isEmpty(captcha.getCaptchaCard())){
            return R.error("验证码为空");
        }
        // 判断验证码是否已使用
        if(captcha.getHasUsed()==0){
            return R.error("验证码已使用，请重新获取");
        }
        // 判断验证码是否过期
        DateTime sendTime = DateUtil.parse(captcha.getSendTime());
        DateTime now = DateUtil.parse(DateUtil.now());
        if(DateUtil.between(sendTime, now, DateUnit.MINUTE)>captcha.getKeepTime()){
            // 验证码已经使用
            updateCaptchaUsedFlag(uuid);
            return R.error("验证码已过期");
        }
        // 验证码错误
        if(!captcha.getCaptchaCard().equals(registerUser.getCaptcha().getCaptchaCard())){
            return R.error("验证码错误");
        }
        // 加密后的密码
        String encrypt = DigestUtil.md5Hex(registerUser.getPassword());
        registerUser.setPassword(encrypt);
        // 用户初始化
        User user = new User(registerUser);
        Long aLong = baseMapper.selectCount(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, user.getUsername()));
        // 账号已经注册
        if (aLong > 0) {
            // 验证码已经使用
            updateCaptchaUsedFlag(uuid);
            return R.error("账号已经注册");
        }
        System.out.println("user = " + user);
        // 将初始化的用户插入数据库
        baseMapper.insert(user);
        // 验证码已经使用
        updateCaptchaUsedFlag(uuid);
        return R.ok("注册成功");
    }

    @Override
    public R sendRegisterCaptcha(String email) {
        // 验证码时限为3分钟
        Integer keepTime = 3;
        boolean isEmail = Validator.isEmail(email);
        if (!isEmail) {
            return R.error("邮箱格式错误，请重新输入");
        }
        Captcha captcha = CommonUtils.generateCaptcha(keepTime);
        captchaMapper.insert(captcha);
        String format = StrUtil.format("验证码发送时间为:{}，您的验证码是:{}，时限为{}分钟，过期失效", captcha.getSendTime(), captcha.getCaptchaCard(), keepTime);
        log.info(format);
        MailUtil.send(email, "验证码", format, false);
        return R.ok("注册验证码发送成功").setData(captcha.getUuid());
    }

    @Override
    public R remakePassword(RemakePasswordUser remakePasswordUser) {
        // 校验验证码
        String uuid = remakePasswordUser.getCaptcha().getUuid();
        // 查找验证码
        Captcha captcha = captchaMapper.selectById(uuid);
        if(StrUtil.isEmpty(captcha.getCaptchaCard())){
            return R.error("验证码为空");
        }
        // 判断验证码是否已使用
        if(captcha.getHasUsed()==0){
            return R.error("验证码已使用，请重新获取");
        }
        // 判断验证码是否过期
        DateTime sendTime = DateUtil.parse(captcha.getSendTime());
        DateTime now = DateUtil.parse(DateUtil.now());
        if(DateUtil.between(sendTime, now, DateUnit.MINUTE)>captcha.getKeepTime()){
            // 验证码已经使用
            updateCaptchaUsedFlag(uuid);
            return R.error("验证码已过期");
        }
        // 验证码错误
        if(!captcha.getCaptchaCard().equals(remakePasswordUser.getCaptcha().getCaptchaCard())){
            return R.error("验证码错误");
        }
        User user = UserThreadLocal.get();
        // 加密后的密码
        String encrypt = DigestUtil.md5Hex(remakePasswordUser.getPassword());
        int update = baseMapper.update(null, new LambdaUpdateWrapper<User>()
                .eq(User::getId, user.getId())
                .set(User::getPassword, encrypt));
        if(update>=0){
            return R.ok("修改成功");
        }else{
            return R.error("修改失败");
        }
    }

    private void updateCaptchaUsedFlag(String uuid) {
        captchaMapper.update(null, new LambdaUpdateWrapper<Captcha>()
                .set(Captcha::getHasUsed, 0)
                .eq(Captcha::getUuid, uuid));
    }
}




